#include "stdafx.h"
#include "resource.h"
#include "EXListCtrl.h"
#include "EXScrollBar.h"
#include <atlbase.h>

// CEXListCtrl

IMPLEMENT_DYNAMIC(CEXListCtrl, CListCtrl)

CEXListCtrl::CEXListCtrl()
{
	m_pVScroll = NULL;
	m_pHScroll = NULL;

	m_bAscend = FALSE;
	m_evenCol = m_oddCol = RGB(255,255,255);

	COLORMAP cm = {RGB(0, 0, 0), GetSysColor(COLOR_GRAYTEXT)};
	m_imglstArrow.Create(9, 5, ILC_COLOR24 | ILC_MASK, 2, 0);
	m_bmpUpArrow.LoadMappedBitmap(IDB_HEADER_UP_S, 0, &cm, 1);
	m_nUpArrow = m_imglstArrow.Add(&m_bmpUpArrow, RGB(255, 255, 255));
	m_bmpDownArrow.LoadMappedBitmap(IDB_HEADER_DOWN_S, 0, &cm, 1);
	m_nDownArrow = m_imglstArrow.Add(&m_bmpDownArrow, RGB(255, 255, 255));
	m_bUseCustomHeader = FALSE;
	m_nSortColumn = -1;
	m_bHeaderLock = FALSE;
}

CEXListCtrl::~CEXListCtrl()
{
}


BEGIN_MESSAGE_MAP(CEXListCtrl, CListCtrl)
	ON_WM_NCCALCSIZE()
	ON_WM_SIZE()
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_ERASEBKGND()
	ON_NOTIFY_REFLECT(LVN_COLUMNCLICK,	&CEXListCtrl::OnLvnColumnclick)
	ON_NOTIFY_REFLECT(NM_CUSTOMDRAW,	&CEXListCtrl::OnNMCustomdraw)
	ON_NOTIFY(HDN_TRACK, 0,				&CEXListCtrl::OnHdnTrack)
	ON_MESSAGE(UM_CUSTOMIZE_HEADER,     &CEXListCtrl::OnCustomsizeHeader)
END_MESSAGE_MAP()



// CEXListCtrl message handlers

LRESULT CEXListCtrl::OnCustomsizeHeader(WPARAM, LPARAM lp)
{
	if (GetParent())
		GetParent()->PostMessage(UM_CUSTOMIZE_HEADER, 0, lp);

	return 0;
}

void CEXListCtrl::SetResSet(CEXBaseResSet* pResSet)
{
  m_pListCtrlResSet = (CEXListCtrlResSet *)pResSet;

  SetListColor(m_pListCtrlResSet->m_crEven, m_pListCtrlResSet->m_crOdd);
  SetFont(m_pListCtrlResSet->m_font);
  SetTextColor(m_pListCtrlResSet->m_crText);

  SubclassHeaderCtrl();

  m_HeaderCtrl.SetResSet(m_pListCtrlResSet->m_headerCtrlResSet);

}

void CEXListCtrl::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
	SCROLLINFO siv = {0};
	siv.cbSize = sizeof(SCROLLINFO);
	siv.fMask = SIF_ALL;

	SCROLLINFO sih = {0};
	sih.cbSize = sizeof(SCROLLINFO);
	sih.fMask = SIF_ALL;

	DWORD dwStyle = GetStyle();

	if (/*bCalcValidRects && */m_pVScroll && m_pHScroll)
	{
		CRect rcWnd;
		GetParent()->GetClientRect(rcWnd);

		CRect rcList;
		m_pVScroll->GetWindowRect(rcList);
		lpncsp->rgrc[0].right = rcWnd.Width() - rcList.Width();
		lpncsp->lppos->cx = lpncsp->rgrc[0].right - lpncsp->rgrc[0].left;

		m_pHScroll->GetWindowRect(rcList);
		lpncsp->rgrc[0].bottom = rcWnd.Height() - rcList.Height();
		lpncsp->lppos->cy = lpncsp->rgrc[0].bottom - lpncsp->rgrc[0].top;
	}

	if (dwStyle & WS_VSCROLL)
	{
		if (GetScrollInfo(SB_VERT, &siv) && m_pVScroll)
		{
			siv.nPage = GetCountPerPage();
			m_pVScroll->SetScrollInfo(&siv);

			if (GetScrollInfo(SB_HORZ, &sih) && m_pHScroll)
			{
				sih.nPage = lpncsp->lppos->cx;
				m_pHScroll->SetScrollInfo(&sih);
			}
 		}
	}

	if (dwStyle & WS_HSCROLL)
	{
		if (GetScrollInfo(SB_HORZ, &sih) && m_pHScroll)
		{
			sih.nPage = lpncsp->lppos->cx;
			m_pHScroll->SetScrollInfo(&sih);

			if (GetScrollInfo(SB_VERT, &siv) && m_pVScroll)
			{
				siv.nPage = GetCountPerPage();
				m_pVScroll->SetScrollInfo(&siv);
			}
 		}
	}

	ModifyStyle(WS_HSCROLL|WS_VSCROLL, WS_CLIPCHILDREN|WS_CLIPSIBLINGS);

	CListCtrl::OnNcCalcSize(bCalcValidRects, lpncsp);
}

void CEXListCtrl::SetScrolls(CEXScrollBar * pVScroll, CEXScrollBar * pHScroll)
{
	m_pVScroll = pVScroll;
	m_pHScroll = pHScroll;
}

LRESULT CEXListCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_PAINT)
	{
		if (m_pVScroll)
		{
			SCROLLINFO siv = {0};
			siv.cbSize = sizeof(SCROLLINFO);
			siv.fMask = SIF_ALL;
			GetScrollInfo(SB_VERT, &siv);
			siv.nPage = GetCountPerPage();
			m_pVScroll->SetScrollInfo(&siv);
		}

		if (m_pHScroll)
		{
			CRect rcList;
			GetClientRect(&rcList);

			SCROLLINFO sih = {0};
			sih.cbSize = sizeof(SCROLLINFO);
			sih.fMask = SIF_ALL;
			GetScrollInfo(SB_HORZ, &sih);
			sih.nPage = rcList.Width();
			m_pHScroll->SetScrollInfo(&sih);
		}
	}
	else if(message == WM_VSCROLL)
	{
		WORD sbCode=LOWORD(wParam);
		if(sbCode == SB_THUMBTRACK || sbCode == SB_THUMBPOSITION)
		{
			int nPos=HIWORD(wParam);

			CRect rcClient;
			GetClientRect(&rcClient);

			SCROLLINFO siv={0};
			siv.cbSize=sizeof(SCROLLINFO);
			siv.fMask=SIF_ALL;

			GetScrollInfo(SB_VERT,&siv);

			SIZE sizeAll;

			if(siv.nPage==0)
				sizeAll.cy=rcClient.bottom;
			else
				sizeAll.cy=rcClient.bottom*(siv.nMax+1)/siv.nPage ;

			SIZE size={0,0};
			size.cy=sizeAll.cy*(nPos-siv.nPos)/(siv.nMax+1);

			Scroll(size);

			return TRUE;
		}
	}
	else if (message == WM_HSCROLL)
	{
		WORD sbCode=LOWORD(wParam);
		if(sbCode == SB_THUMBTRACK || sbCode == SB_THUMBPOSITION)
		{
			int nPos=HIWORD(wParam);

			CRect rcClient;
			GetClientRect(&rcClient);

			SCROLLINFO sih={0};
			sih.cbSize=sizeof(SCROLLINFO);
			sih.fMask=SIF_ALL;

			GetScrollInfo(SB_HORZ,&sih);

			SIZE sizeAll;
			if(sih.nPage==0) 
				sizeAll.cx=rcClient.right;
			else
				sizeAll.cx=rcClient.right*(sih.nMax+1)/sih.nPage ;

			SIZE size={0,0};
			size.cx=sizeAll.cx*(nPos-sih.nPos)/(sih.nMax+1);

			Scroll(size);

			return TRUE;
		}
	}


	return CListCtrl::WindowProc(message, wParam, lParam);
}

void CEXListCtrl::OnSize(UINT nType, int cx, int cy)
{
	CListCtrl::OnSize(nType, cx, cy);

	if (IsWindow(GetSafeHwnd()))
	{
		if (m_pVScroll && IsWindow(m_pVScroll->GetSafeHwnd()))
		{
			SCROLLINFO siv = {0};
			siv.cbSize = sizeof(SCROLLINFO);
			siv.fMask = SIF_ALL;
			GetScrollInfo(SB_VERT, &siv);
			siv.nPage = GetCountPerPage();
			m_pVScroll->SetScrollInfo(&siv/*, FALSE*/);
		}

		if (m_pHScroll && IsWindow(m_pHScroll->GetSafeHwnd()))
		{
			CRect rcList;
			GetClientRect(&rcList);

			SCROLLINFO sih = {0};
			sih.cbSize = sizeof(SCROLLINFO);
			sih.fMask = SIF_ALL;
			GetScrollInfo(SB_HORZ, &sih);
			sih.nPage = rcList.Width();
			m_pHScroll->SetScrollInfo(&sih/*, FALSE*/);
		}
	}
}

void CEXListCtrl::SetFont(CFont* pFont, BOOL bRedraw /*= TRUE*/)
{
	LOGFONT lf = {0};
	pFont->GetLogFont(&lf);
	lf.lfWeight = FW_BOLD;

	CFont ftNew;
	ftNew.CreateFontIndirect(&lf);

	GetHeaderCtrl()->SetFont(&ftNew, bRedraw);

	CListCtrl::SetFont(pFont, bRedraw);
}

void CEXListCtrl::OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

	if (!m_bHeaderLock)
		Sort(pNMLV->iSubItem, m_bAscend);

	*pResult = 0;
}

void CEXListCtrl::Sort()
{
	if (m_nSortColumn != -1)
		Sort(m_nSortColumn, !m_bAscend);
}

void CEXListCtrl::Sort(int nColumn, BOOL bAscend)
{
	WCHAR str[20];

	HDITEM temp;
	temp.cchTextMax = 20;
	temp.pszText = str;
	temp.mask = HDI_TEXT ;

	CRect rect;

	GetHeaderCtrl()->GetItem(nColumn, &temp);
	GetHeaderCtrl()->GetItemRect(nColumn, &rect);

	SORT_INFO sf;
	sf.nColumn = nColumn;
	sf.plist = this;
	sf.bAscend = !bAscend;

	m_bAscend = !bAscend;
	m_nSortColumn = nColumn;

	SetSortIcon(nColumn);

	ListView_SortItemsEx(GetSafeHwnd(), SortList, reinterpret_cast<LPARAM>(&sf));
}

void CEXListCtrl::SetSortIcon(int nIndex)
{
	CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
	ASSERT(pHeaderCtrl);

	for (int col = 0; col <= pHeaderCtrl->GetItemCount(); col++)
	{
		HDITEM hdrItem = {0};

		hdrItem.mask = HDI_FORMAT | HDI_IMAGE | HDI_LPARAM;
		pHeaderCtrl->GetItem(col, &hdrItem);

		if (nIndex == col && m_bAscend)
		{
			hdrItem.iImage = m_nDownArrow;
			hdrItem.fmt = hdrItem.fmt & HDF_JUSTIFYMASK | HDF_IMAGE | HDF_STRING | 
                                  HDF_BITMAP_ON_RIGHT;
			hdrItem.lParam = (LPARAM)1;
		}
		else if (nIndex == col && !m_bAscend)
		{
			hdrItem.iImage = m_nUpArrow;
			hdrItem.fmt = hdrItem.fmt & HDF_JUSTIFYMASK | HDF_IMAGE | HDF_STRING | 
                                  HDF_BITMAP_ON_RIGHT;
			hdrItem.lParam = (LPARAM)1;
		}
		else
		{
			hdrItem.fmt = hdrItem.fmt & HDF_JUSTIFYMASK | HDF_STRING;
			hdrItem.lParam = (LPARAM)0;
		}

		pHeaderCtrl->SetItem(col, &hdrItem);
	}
}

int CALLBACK CEXListCtrl::SortList( LPARAM lItemIndex1_i, LPARAM lItemIndex2_i, 
                                   LPARAM lCustomParam_i )
{
	SORT_INFO * sf = (SORT_INFO *)lCustomParam_i;

	CListCtrl * pList = sf->plist;

	CString str1 = pList->GetItemText(int(lItemIndex1_i), sf->nColumn);
	CString str2 = pList->GetItemText(int(lItemIndex2_i), sf->nColumn);

	BOOL bDigit = TRUE;
	for (int i=0; i<str1.GetLength(); i++)
	{
		if (!iswdigit(str1[i]))
		{
			bDigit = FALSE;
			break;
		}
	}

	for (int i=0; bDigit && i<str2.GetLength(); i++)
	{
		if (!iswdigit(str2[i]))
		{
			bDigit = FALSE;
			break;
		}
	}

	if (bDigit)
	{
		WCHAR lpBuffer[256];

		HDITEM hdi;
		hdi.mask = HDI_TEXT;
		hdi.pszText = lpBuffer;
		hdi.cchTextMax = 256;

		if (sf->plist->GetHeaderCtrl()->GetItem(sf->nColumn, &hdi))
		{
			{
				int nValue1 = _wtoi(str1);
				int nValue2 = _wtoi(str2);

				if (sf->bAscend)
					return nValue2 > nValue1;
				else
					return nValue1 > nValue2;
			}
		}
		else
		{
			if(sf->bAscend)
				return str2.Compare(str1);
			else
				return str1.Compare(str2);
		}
	}
	else
	{
		if(sf->bAscend)
			return str2.Compare(str1);
		else
			return str1.Compare(str2);
	}
}

void CEXListCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
	NMLVCUSTOMDRAW * plvCstDrawPtr = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);

	int nItem = static_cast<int> (plvCstDrawPtr->nmcd.dwItemSpec);
	int nSubItem = plvCstDrawPtr->iSubItem;

	*pResult = CDRF_DODEFAULT;
  
	if (plvCstDrawPtr->nmcd.dwDrawStage == CDDS_PREPAINT)
	{
		*pResult = CDRF_NOTIFYITEMDRAW;
	}
	else if (plvCstDrawPtr->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
	{
		if( plvCstDrawPtr->nmcd.dwItemSpec & 1 )
		{
			plvCstDrawPtr->clrTextBk = m_oddCol;
		}
		else
		{
			plvCstDrawPtr->clrTextBk = m_evenCol;
		}
  }
}

void CEXListCtrl::GetDrawColors(int nItem,
							   int nSubItem,
							   COLORREF& colorText,
							   COLORREF& colorBkgnd)
{

}

void CEXListCtrl::DrawText(int nItem,
						  int nSubItem,
						  CDC *pDC,
						  COLORREF crText,
						  COLORREF crBkgnd,
						  CRect& rect)
{
	ASSERT(pDC);

	CRect rcNew;
	rcNew = rect;

	pDC->FillSolidRect(&rect, crBkgnd);


	CString str(_T(""));
	str = GetItemText(nItem, nSubItem);	
  
  HDITEM hditem;
  hditem.mask = HDI_FORMAT;
  GetHeaderCtrl()->GetItem(nSubItem, &hditem);

  int nFmt = hditem.fmt & HDF_JUSTIFYMASK;
  UINT nFormat = DT_VCENTER | DT_SINGLELINE;

  if (nFmt == HDF_CENTER)
  {
    nFormat |= DT_CENTER;
  }
  else if (nFmt == HDF_LEFT)
  {
    nFormat |= DT_LEFT;
    rcNew.left += 4;
  }
  else
  {
    nFormat |= DT_RIGHT;
  }

  pDC->SetBkMode(TRANSPARENT);
  rcNew.OffsetRect(0, 1);
  pDC->DrawText(str, &rcNew, nFormat);
}

void CEXListCtrl::SetListCtrlName(CString strName)
{
	m_strName = strName;
}

void CEXListCtrl::OnDestroy()
{
	CListCtrl::OnDestroy();

	DWORD dwHeaderCount = GetHeaderCtrl()->GetItemCount();
	int * pOrder = new int[dwHeaderCount];

	GetColumnOrderArray(pOrder, dwHeaderCount);

	CString strOrder;
	CString strWidth;
	CString strVisible;
	CString strTemp;

	for(DWORD i = 0;i < dwHeaderCount; i++)
	{
		strTemp.Empty();
		strTemp.Format(L"%d ", pOrder[i]);
		strOrder += strTemp;

		strTemp.Empty();
		strTemp.Format(L"%d ", CListCtrl::GetColumnWidth(i));
		strWidth += strTemp;

		strTemp.Empty();
		strTemp.Format(L"%d ", CListCtrl::GetColumnWidth(i) == 0 ? FALSE : TRUE);
		strVisible += strTemp;

#ifdef _DEBUG
		HDITEM hdi;
		enum   { sizeOfBuffer = 256 };
		TCHAR  lpBuffer[sizeOfBuffer];

		hdi.mask = HDI_TEXT;
		hdi.pszText = lpBuffer;
		hdi.cchTextMax = sizeOfBuffer;

		GetHeaderCtrl()->GetItem(i, &hdi);
		TRACE(L"\n%d %d %s", pOrder[i], CListCtrl::GetColumnWidth(i), hdi.pszText);
#endif // _DEBUG
	}

	delete [] pOrder;
}

int CEXListCtrl::FindIndex(int nItem)
{
	HDITEM hdi = {0};
	hdi.mask = HDI_WIDTH;

	while (nItem >= 0)
	{
		GetHeaderCtrl()->GetItem(nItem, &hdi);
		if (hdi.cxy != 0)
			break;

		nItem = nItem-1;
	}

	return nItem;
}

void CEXListCtrl::OnHdnTrack(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);

	HDITEM hdi = {0};
	hdi.mask = HDI_WIDTH;
	GetHeaderCtrl()->GetItem(phdr->iItem, &hdi);

	if (hdi.cxy == 0)
	{
		phdr->pitem->cxy = 0;
	}

	SCROLLINFO siv={0};
	siv.cbSize=sizeof(SCROLLINFO);
	siv.fMask=SIF_ALL;
	SCROLLINFO sih=siv;
	GetScrollInfo(SB_VERT, &siv);
	GetScrollInfo(SB_HORZ, &siv);

	*pResult = 0;
}

int CEXListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CListCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;

	return 0;
}

void CEXListCtrl::PreSubclassWindow()
{
	CListCtrl::PreSubclassWindow();
}

void CEXListCtrl::SubclassHeaderCtrl()
{
	VERIFY(m_HeaderCtrl.SubclassWindow(GetHeaderCtrl()->GetSafeHwnd()));
	m_bUseCustomHeader = TRUE;

	GetHeaderCtrl()->SetImageList(&m_imglstArrow);

	SetFont(GetFont());
}

void CEXListCtrl::SetHeaderBitmap(UINT nID)
{
	ASSERT(m_bUseCustomHeader);

	m_HeaderCtrl.SetHeaderBitmap(nID);
}

int CEXListCtrl::InsertColumn(int nCol, const LVCOLUMN* pColumn)
{
	if (!GetHeaderCtrl()->GetItemCount())
	{
		LVCOLUMN lvc = *pColumn;
		lvc.cx = 0;
		if (CListCtrl::InsertColumn(0, &lvc) == -1)
			return -1;
	}

	nCol++;

	COLUMN_DATA cd = { nCol, pColumn->cx, TRUE };
	m_arrHeaderItem.Add(cd);

	return CListCtrl::InsertColumn(nCol, pColumn);
}

int CEXListCtrl::InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat, 
                              int nWidth, int nSubItem)
{
	if (!GetHeaderCtrl()->GetItemCount())
	{
		if (CListCtrl::InsertColumn(0, L"", LVCFMT_LEFT, 0, -1) == -1)
			return -1;
	}

	nCol++;

	COLUMN_DATA cd = { nCol, nWidth, TRUE };
	m_arrHeaderItem.Add(cd);

	return CListCtrl::InsertColumn(nCol,lpszColumnHeading,nFormat,nWidth,nSubItem);
}

int CEXListCtrl::InsertItem(const LVITEM* pItem)
{
	int nItem = CListCtrl::InsertItem(pItem->iItem, L"");
	if (nItem == -1)
		return -1;

	LVITEM lvi = *pItem;
	lvi.iSubItem = 0;

	if (!SetItem(&lvi))
	{
		DeleteItem(nItem);
		return -1;
	}
	
	return nItem;
}

int CEXListCtrl::InsertItem(int nItem, LPCTSTR lpszItem)
{
	int nIdx = CListCtrl::InsertItem(nItem, L"");
	if (nIdx == -1)
		return -1;

	if (!SetItem(nIdx, 0, LVIF_TEXT, lpszItem, 0, 0, 0, 0))
	{
		DeleteItem(nIdx);
		return -1;
	}

	return nIdx;
}

int CEXListCtrl::InsertItem(int nItem, LPCTSTR lpszItem, int nImage)
{
	int nIdx = CListCtrl::InsertItem(nItem, L"");
	if (nIdx == -1)
		return -1;

	if (!SetItem(nIdx, 0, LVIF_IMAGE|LVIF_TEXT, lpszItem, nImage, 0, 0, 0))
	{
		DeleteItem(nIdx);
		return -1;
	}

	return nIdx;
}

BOOL CEXListCtrl::SetItem(const LVITEM* pItem)
{
	LVITEM lvi = *pItem;
	lvi.iSubItem++;
	return CListCtrl::SetItem(&lvi);
}

BOOL CEXListCtrl::SetItem(int nItem, int nSubItem, UINT nMask, LPCTSTR lpszItem,
			                  int nImage, UINT nState, UINT nStateMask, LPARAM lParam)
{
	return CListCtrl::SetItem(nItem, nSubItem+1, nMask, lpszItem, nImage, nState, 
                            nStateMask, lParam);
}

BOOL CEXListCtrl::SetItem(int nItem, int nSubItem, UINT nMask, LPCTSTR lpszItem,
			                    int nImage, UINT nState, UINT nStateMask, 
                          LPARAM lParam, int nIndent)
{
	return CListCtrl::SetItem(nItem, nSubItem+1, nMask, lpszItem, nImage, nState, 
                            nStateMask, lParam, nIndent);
}

BOOL CEXListCtrl::GetColumn(int nCol, LVCOLUMN* pColumn) const
{
	return CListCtrl::GetColumn(nCol+1, pColumn);
}

BOOL CEXListCtrl::SetColumn(int nCol, const LVCOLUMN* pColumn)
{
	return CListCtrl::SetColumn(nCol+1, pColumn);
}

int CEXListCtrl::GetColumnWidth(int nCol) const
{
	return CListCtrl::GetColumnWidth(nCol+1);
}

BOOL CEXListCtrl::SetColumnWidth(int nCol, int cx)
{
	return CListCtrl::SetColumnWidth(nCol+1, cx);
}

CString CEXListCtrl::GetItemText(int nItem, int nSubItem) const
{
	return CListCtrl::GetItemText(nItem, nSubItem+1);
}

int CEXListCtrl::GetItemText(__in int nItem, __in int nSubItem, 
                         __out_ecount_part_z(nLen, return + 1) LPTSTR lpszText, 
                         __in int nLen) const
{
	return CListCtrl::GetItemText(nItem, nSubItem+1, lpszText, nLen);
}

BOOL CEXListCtrl::SetItemText(int nItem, int nSubItem, LPCTSTR lpszText)
{
	return CListCtrl::SetItemText(nItem, nSubItem+1, lpszText);
}

BOOL CEXListCtrl::SetColumnOrderArray(int iCount, LPINT piArray)
{
	iCount++;

	LPINT pnOrder = (LPINT) malloc(iCount*sizeof(int));
	ASSERT(pnOrder != NULL);

	pnOrder[0] = 0;
	for (int i=1; i<iCount; i++)
	{
		pnOrder[i] = piArray[i-1]+1;
	}

	BOOL bRet = CListCtrl::SetColumnOrderArray(iCount, pnOrder);

	free(pnOrder);

	return bRet;
}

BOOL CEXListCtrl::GetColumnOrderArray(LPINT piArray, int iCount /*= -1*/)
{
	if (iCount == -1)
		iCount = GetHeaderCtrl()->GetItemCount();

	if (!CListCtrl::GetColumnOrderArray(piArray, iCount))
	{
		return FALSE;
	}

	return TRUE;
}

BOOL CEXListCtrl::GetSubItemRect(int iItem, int iSubItem, int nArea, CRect& ref)
{
	return CListCtrl::GetSubItemRect(iItem, iSubItem+1, nArea, ref);
}

BOOL CEXListCtrl::DeleteColumn(int nCol)
{
	if (CListCtrl::DeleteColumn(nCol+1))
	{
		if (GetHeaderCtrl()->GetItemCount() == 1)
			DeleteColumn(0);

		return TRUE;
	}
	return FALSE;
}

BOOL CEXListCtrl::OnEraseBkgnd(CDC* pDC)
{
	return CListCtrl::OnEraseBkgnd(pDC);
}


void CEXListCtrl::SetHeaderColor(COLORREF crHeader)
{
	m_HeaderCtrl.SetBkgndColor(crHeader);
}

void CEXListCtrl::SetListColor(COLORREF crEven, COLORREF crOdd)
{
	m_evenCol = crEven;
	m_oddCol = crOdd;

	Invalidate(FALSE);
}

void CEXListCtrl::LockHeader()
{
	m_bHeaderLock = TRUE;
	m_HeaderCtrl.EnableWindow(FALSE);
}

void CEXListCtrl::UnlockHeader()
{
	m_bHeaderLock = FALSE;
	m_HeaderCtrl.EnableWindow(TRUE);
}

void CEXListCtrl::GetSortColumn(CString & strColumn, BOOL & bAscend)
{
	if (m_nSortColumn != -1)
	{
		HDITEM hdi = {0};
		enum   { sizeOfBuffer = 256 };
		TCHAR  lpBuffer[sizeOfBuffer] = {0};

		hdi.mask = HDI_TEXT;
		hdi.pszText = lpBuffer;
		hdi.cchTextMax = sizeOfBuffer;

		m_HeaderCtrl.GetItem(m_nSortColumn, &hdi);
		strColumn = hdi.pszText;
		bAscend = m_bAscend;
	}
}

